package com.xb.loan.admin.web.controller;

import com.xb.loan.admin.Constants;
import com.xb.loan.admin.bean.dict.DictEnum;
import com.xb.loan.admin.bean.system.OssOperateLog;
import com.xb.loan.admin.service.dict.DictEnumService;
import com.xb.loan.admin.service.dict.IenumConstants;
import com.xb.loan.admin.service.monitor.OssOperateLogService;
import com.xb.loan.admin.util.DictEnumConst;
import com.xb.loan.admin.util.PartnerUtil;
import com.xb.loan.log.bean.UserLogVO;
import com.xb.loan.log.constant.LogConst;
import com.xb.loan.log.exception.BizException;
import com.xb.loan.util.DateHelper;
import com.xb.loan.util.cache.redis.RedisQueueManager;
import com.xb.loan.util.cache.redis.comm.FormatOperation;

import com.xb.loan.util.queue.Queue;
import org.apache.commons.io.output.FileWriterWithEncoding;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.SessionAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.math.BigDecimal;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


@SessionAttributes("getLoginType")  
public abstract class BaseController {
	/*默认 1    页面显示的第几页*/
	@Value("${page.pageNum}")
	private String pageNum;
	/*默认20 页面显示的条数*/
	@Value("${page.numPerPage}")
    private String numPerPage;
    
    /*站内信息图片上传路径*/
    @Value("${user.msg.path}")
    private String userMsgPath;
    
    /*系统消息图片上传路径*/
    @Value("${user.sysmsg.path}")
    private String userSysMsgPath;
    
    /*活动管理图片上传路径*/
    @Value("${user.activity.path}")
    private String userActivityPath;
    
    /*图片的最大字节数*/
    @Value("${image.file.max}")
    private long imageFileMax;
    
    /*默认导出记录条数5000*/
    @Value("${export.csv.maxRecordSize}")
    private String exportCSVMaxRecordSize;

    
    protected int getExportCSVMaxRecordSize(){
        return Integer.parseInt(exportCSVMaxRecordSize);
    }
    protected int getPageNum(){
        return Integer.parseInt(pageNum);
    }
    protected int getNumPerPage(){
        return Integer.parseInt(numPerPage);
    }
    
    public String getUserMsgPath() {
		return userMsgPath;
	}
	public void setUserMsgPath(String userMsgPath) {
		this.userMsgPath = userMsgPath;
	}
	public String getUserSysMsgPath() {
		return userSysMsgPath;
	}
	public void setUserSysMsgPath(String userSysMsgPath) {
		this.userSysMsgPath = userSysMsgPath;
	}
	public String getUserActivityPath() {
		return userActivityPath;
	}
	public void setUserActivityPath(String userActivityPath) {
		this.userActivityPath = userActivityPath;
	}

	public long getImageFileMax() {
		return imageFileMax;
	}
	public void setImageFileMax(long imageFileMax) {
		this.imageFileMax = imageFileMax;
	}




	protected static final String OPERATE_RESULT_SUCCESS_MSG = "操作成功!";
    protected static final String OPERATE_RESULT_FAILURE_MSG = "操作失败!";
    protected static final String OPERATE_RESULT_EXCEPTION_MSG = "系统异常!";
    
    protected static final String OPERATE_RESULT_SUCCESS_CODE = "0";
    protected static final String OPERATE_RESULT_FAILURE_CODE = "1";
    protected static final String OPERATE_RESULT_EXCEPTION_CODE = "-1";
    
    protected static final String Show_Prize_Notice = "show_prize_notice";

    @Autowired
    protected DictEnumService dictEnumService;
    @Autowired
    protected OssOperateLogService ossOperateLogService;

    
    protected final static String CSV_FILE_SUFFIX=".csv";
    protected final static String ZIP_FILE_SUFFIX=".zip";
    
  
    /**
     * 获取当前登录用户的类型，0：平台用户，1：客服用户
     * @param req
     * @param model
     */
    protected void getLoginUserType(HttpServletRequest req, Model model){
    	String loginType = (String)req.getSession().getAttribute(Constants.SESSION_LOGIN_USER_TYPE);
    	if(loginType == null || "".equals(loginType) || loginType.length() < 1){
    		loginType = "0";
    	}
    	model.addAttribute("loginUserType", loginType);
    }
    
    /**
     * 
     * 将指定文件夹打包成zip
     * @param folder
     * @param nowTime
     * @throws FileNotFoundException
     * @throws IOException
     * @return 生成的zip文件路径
     * 2015年11月11日 by zhiqiang.zhang
     */
    protected  String makeZipFile(String nowTime,String folder) throws FileNotFoundException,IOException   {
        
        String zipFilePath=System.getProperty("java.io.tmpdir") + File.separator+nowTime+ ZIP_FILE_SUFFIX;   
        
        File zipFile = new File(zipFilePath);
        if (zipFile.exists()) {
            zipFile.delete();
        }
        
        File dir = new File(folder);
        File[] fs = dir.listFiles();
        byte[] buf = null;
        ZipOutputStream zipout=null;
        try {
            zipout = new ZipOutputStream(new FileOutputStream(zipFile));
            if(fs!=null){
                for (File f : fs) {
                    zipout.putNextEntry(new ZipEntry(f.getName()));
                    
                    FileInputStream fileInputStream =null;
                    BufferedInputStream origin =null;
                    try{
                        fileInputStream =new FileInputStream(f);
                        buf = new byte[2048];
                        origin = new BufferedInputStream(fileInputStream,2048);
                        int len;
                        while ((len = origin.read(buf,0,2048))!=-1) {
                            zipout.write(buf,0,len);
                        }
                    }finally{
                        if(origin!=null){
                            origin.close();
                        }
                        if(fileInputStream!=null){
                            fileInputStream.close();
                        }
                    }
                    
                    zipout.flush();
                    
                }
            }
            zipout.flush();
        }finally{
            if(zipout!=null){
                zipout.close();
            }

        }
        return zipFilePath;
    }
    /**
     * 
     * 生成CSV文件
     * @param nowTime
     * @param csvHeader
     * @param fieldName
     * @param dataList
     * @return CSV文件所在目录
     * @throws IOException
     * 2015年11月11日 by zhiqiang.zhang
     */
    @SuppressWarnings("rawtypes")
    protected String writeCSVFile(String nowTime, String csvHeader, FieldName[] fieldName, List dataList) throws IOException {
        return this.writeCSVFile(nowTime, csvHeader, fieldName, dataList,false,false);
    }
    /**
     * 
     * 生成CSV文件
     * @param nowTime
     * @param csvHeader
     * @param fieldName
     * @param dataList  
     * @param isOutputSN 是否输出序号列，true输出，false不输出
     * @param isOutputTotal 是否输出合计行，true输出，false不输出
     * @return CSV文件所在目录
     * @throws IOException
     * 2015年11月11日 by zhiqiang.zhang
     */
    @SuppressWarnings("rawtypes")
    protected String writeCSVFile(String nowTime, String csvHeader, FieldName[] fieldName, List dataList,boolean isOutputSN,boolean isOutputTotal) throws IOException {
        //String fileName=nowTime+CSV_FILE_SUFFIX;
        String csvFileFolder=System.getProperty("java.io.tmpdir") + File.separator+nowTime;
        File f_csvFileFolder=new File(csvFileFolder);
        if(!f_csvFileFolder.exists()){
            f_csvFileFolder.mkdir();
        }
        String csvFilePath = csvFileFolder+File.separator +nowTime+ CSV_FILE_SUFFIX;
        
        BufferedInputStream bis = null;
        BufferedOutputStream out = null;
        File file = new File(csvFilePath);
        FileWriterWithEncoding fwwe = null;
        BufferedWriter bw = null;
        try {
            fwwe = new FileWriterWithEncoding(file, "GBK");
            bw = new BufferedWriter(fwwe);

            bw.write(csvHeader);
            bw.write("\n");

            int fieldNameLength = fieldName.length;

            //合计总数
            //汇总需要累计的字段数量
            int sumNum = 0;
            for (int j = 0; j < fieldNameLength; j++) {
                if (fieldName[j].isTotal()) {
                    sumNum++;
                }
            }
            //存放合计数值变量数组
            BigDecimal[] sumMoneyArray = new BigDecimal[sumNum];
            for (int i = 0; i < sumNum; i++) {
                sumMoneyArray[i] = new BigDecimal(0);
            }
            
            long dataListSize = dataList.size();

            for (int i = 0; i < dataListSize; i++) {
                Map map = (Map) dataList.get(i);
                StringBuilder line = new StringBuilder();
                
                if(isOutputSN){//是否输出序号列
                    //序号
                    line.append(i + 1+",");
                }

                for (int j = 0, sumIndex = 0; j < fieldNameLength; j++) {
                	if(map.get(fieldName[j].getName()) != null){
                		line.append((map.get(fieldName[j].getName())+"").replace(",", "，") + "\t");
                	}else{
                		line.append("");
                	}
                    if(j!=fieldNameLength-1){
                        line.append(",");
                    }
                    
                    if (fieldName[j].isTotal()) {
                    	String intNum = "0";
                    	if(map.get(fieldName[j].getName()) != null){
                    		intNum = map.get(fieldName[j].getName()).toString();
                    	}
                    	BigDecimal bdTemp = new BigDecimal(intNum);
                        sumMoneyArray[sumIndex] = sumMoneyArray[sumIndex].add(bdTemp);
                        sumIndex++;
                    }
                }
                //换行
                line.append("\n");
                bw.write(line.toString());

                if (i % 1000 == 0) {
                    bw.flush();
                }
            }

            if(isOutputTotal){
                bw.write("总计");
                
 
                for (int j = (isOutputSN?0:1), sumIndex = 0; j < fieldNameLength; j++) {
                    bw.write(",");
                    if (fieldName[j].isTotal()) {
                        bw.write(sumMoneyArray[sumIndex++].toString());
                    }

                }   
            }


            bw.flush();
        }

        finally {
            try {
                if (bis != null) {
                    bis.close();
                }
            } catch (IOException e) {

            }
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
            }
            try {
                bw.close();
            } catch (IOException e) {

            }
            try {
                fwwe.close();
            } catch (IOException e) {

            }
        }
        
        return csvFileFolder;
    }
    
    /**
     * 
     * 删除文件夹及其下所有文件
     * @param folderPath
     * @return
     * 2015年11月11日 by zhiqiang.zhang
     */
    protected boolean deleteFolder(String folderPath){
        File dir=new File(folderPath);
        if (dir.isDirectory()) {
            String[] children = dir.list();
            for (int i=0; i<children.length; i++) {
                File childFile=new File(dir,children[0]);
                childFile.delete();
            }
        }
        // 目录此时为空，可以删除
        return dir.delete(); 
    }
    /**
     * 
     * 删除文件
     * @param filePath
     * @return
     * 2015年11月11日 by zhiqiang.zhang
     */
    protected boolean deleteFile(String filePath){
        File dir=new File(filePath);
        return dir.delete(); 
    }
    protected String getNowTime(){
        return DateHelper.DateToString("yyyyMMddHHmm",new Date());
    }

    protected void csvDownLoad(String nowTime,String zipFilepath,String csvFileFolder,HttpServletResponse response) throws BizException, IOException   {

        response.setContentType("application/zip");
        response.addHeader("Content-Disposition", "attachment; filename=" + nowTime + ZIP_FILE_SUFFIX);

        FileInputStream inputStream = null;
        OutputStream outputStream = null;
        File file = new File(zipFilepath);

        //将此文件流写入到response输出流中
        byte[] buffer = new byte[1024];
        int i = -1;
        try {
            inputStream = new FileInputStream(file);
            outputStream = response.getOutputStream();
            while ((i = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, i);
            }
            outputStream.flush();
        } finally {
            if (outputStream != null) {
                outputStream.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
            
            //删除生成的文件
            this.deleteFile(zipFilepath);
            this.deleteFolder(csvFileFolder);   
        }

        

    }
    
    
    
    
    
    /**
     * 
     * 获得操作员登录帐号
     * @param request
     * @return
     * 2015年11月10日 by zhiqiang.zhang
     */
    public String getLoginName(HttpServletRequest request){
        
        return (String)request.getSession().getAttribute(Constants.SESSION_LOGIN_NAME);
    }
    
    /**
     * 
     * 获得操作员登录编码
     * @param request
     * @return
     * 2015年11月10日 by zhiqiang.zhang
     */
    public String getOperatorId(HttpServletRequest request){
        
        return (String)request.getSession().getAttribute(Constants.SESSION_OPERATOR_ID);
    }
    
    
    
    
    /**
     * 
     * 根据中心OSS中登录用户权限和要查询的渠道级别，组织查询的SQL的where条件字符串
     * @param partnerLevel
     * @param authorityPartnerIdStr
     * @param partnerId
     * @return
     * 2015年11月3日 by zhiqiang.zhang
     */
    protected String getPartnerDataQueryAuthoritySQL(String partnerLevel,String authorityPartnerIdStr,String partnerId){
        
        return PartnerUtil.getPartnerDataQueryAuthoritySQL(partnerLevel, authorityPartnerIdStr, partnerId);
    }
    
    /**
     * 
     * 返回渠道查询的SQL语句的Where条件的，只包含like '渠道ID%' 部分  
     * @param authorityPartnerIdStr 操作员可查看的渠道编号
     * @return where语句的like条件字符串
     * 2015年11月27日 by zhiqiang.zhang
     */
    protected String getPartnerDataQueryAuthoritySQL(String authorityPartnerIdStr){
        
        return PartnerUtil.getPartnerDataQueryAuthoritySQL( authorityPartnerIdStr);
    }
    
    protected String getPartnerDataQueryAuthoritySQL(HttpServletRequest request){
    	//可查看渠道列表
        String partnerIds=(String)request.getSession().getAttribute(Constants.SESSION_ROLE_PARTNER_STR);
		//中心oss操作员拥有的查询渠道数据
        return this.getPartnerDataQueryAuthoritySQL(partnerIds);
    }
    
    
    

    /**
     * 
     * 获得证件类型
     * @param model
     * @throws BizException
     * 2015年11月3日 by zhiqiang.zhang
     */
    protected void getCardType(Model model) throws BizException{
        List<DictEnum> cardType = dictEnumService.queryDictEnumByType(DictEnumConst.CARD_TYPE);
        model.addAttribute("cardType",cardType);
        
    }
    /**
     *
     * 获得支付卡类型

    protected void getPayCardType(Model model) throws BizException{
        List<CashierPayChannelBankBO> paycardType = dubboEncashOrderService.queryPayChannelBanksByPage(1,this.getExportCSVMaxRecordSize(), null);
        model.addAttribute("paycardType",paycardType);

    } */
    
    //查看是否有 该权限
    @SuppressWarnings("unchecked")
    protected List<Map<String,Boolean>> getAccessPage(String[] str,HttpServletRequest req,Map<String,Object> mapResult){
    	List<String> listAccesss = (List<String>) req.getSession().getAttribute(Constants.SESSION_AUTHORIZATION_LIST);
    	List<Map<String,Boolean>> list = new ArrayList<Map<String,Boolean>>();
    	Map<String,Boolean> map = new HashMap<String,Boolean>();
    	for (String string : str) {
    		if(listAccesss.contains(string)){
    			map.put("key"+string, true);
    		}else{
    			map.put("key"+string, false);
    		}
		}
    	list.add(map);
    	if(mapResult != null){
    		mapResult.put("listAccess", list);
    	}
    	return list;
    }

    /**
     * 操作日志添加
     * @param req           HttpServletRequest,获取Session中的数据
     * @param objectType    操作表名
     * @param content       操作描述
     * @param objectId      操作表名主键
     * @param operateType   操作类型
     * @throws BizException
     * 2015年12月28日 by wuqinglong
     */
    protected void addOperateLog(HttpServletRequest req,String objectType,String content,String objectId,Integer operateType)throws BizException{
        HttpSession session = req.getSession();
        String operatorId = (String) session.getAttribute(Constants.SESSION_OPERATOR_ID);
        String operatorName = (String) session.getAttribute(Constants.SESSION_LOGIN_NAME);
        String partnerId = (String) session.getAttribute(Constants.SESSION_PARTNER_ID);
        String operateLogId = FormatOperation.assemblySeq(
                IenumConstants.PriKeyStrategy.OSS_OPERATOR.getCode(),
                IenumConstants.PriKeyStrategy.OSS_OPERATOR.getNum(),
                FormatOperation.formatDateToYMDHms(new Date()), "");
        OssOperateLog ossOperateLog = new OssOperateLog();
        ossOperateLog.setOperateLogId(Long.valueOf(operateLogId));
        ossOperateLog.setOperatorId(operatorId);
        ossOperateLog.setObjectType(objectType);
        ossOperateLog.setObjectContent(operatorName+content);
        ossOperateLog.setObjectId(objectId);
        ossOperateLog.setOperateType(operateType);
        ossOperateLog.setPartnerId(partnerId);
        ossOperateLogService.insertOssOperateLog(ossOperateLog);
    }
    
    
    /**
     * 操作日志添加
     * @param req		HttpServletRequest,获取Session中的数据
     * @param logType	日志类型
     * @param content	日志内容
     * @param logModule	操作模板
     * @param userId    修改用户编码
     * @throws BizException
     */
    protected void addUserLog(HttpServletRequest req,Integer logType,String content,String logModule,String userId)throws BizException{
        HttpSession session = req.getSession();
        String operatorName = (String) session.getAttribute(Constants.SESSION_LOGIN_NAME);
        String partnerId = (String) session.getAttribute(Constants.SESSION_PARTNER_ID);    
        
        UserLogVO logVO= new UserLogVO();
        logVO.setUserId(userId);
        logVO.setLogType(logType);
        logVO.setUserType(30);
        logVO.setLogLevel(0);
        logVO.setLogContent("操作人："+operatorName+",操作描述："+content);
        logVO.setLogModule(logModule);
        
        Queue<UserLogVO> logQueue = RedisQueueManager.getQueue(LogConst.RedisQueue_Log, UserLogVO.class);
        logQueue.add(logVO);
    }
    
    
    protected void customErrorHandle(BizException e,Object obj,String objName,Model model){
    	String errorMsg = e.getMessage();
    	model.addAttribute(objName, obj); 
    	if(errorMsg != null && errorMsg.length() > 0){
    		model.addAttribute("errorMsg", errorMsg);
    	}else{
    		model.addAttribute("errorMsg", "系统异常，请联系管理员");
    	}
    	
    }
}
